// class: 传统的JavaScript程序使用函数和基于原型的继承来创建可重用的组件，但对于熟悉使用面向对象方式的程序员来讲就有些棘手，因为他们用的是基于类的继承并且对象是由类构建出来的。 从ECMAScript 2015，也就是ECMAScript 6开始，JavaScript程序员将能够使用基于类的面向对象的方式。 使用TypeScript，我们允许开发者现在就使用这些特性，并且编译后的JavaScript可以在所有主流浏览器和平台上运行，而不需要等到下个JavaScript版本
class Creeter {
  greeting: string;
  constructor(message: string) {
    this.greeting = message;
  }
  greet(): string {
    return `Hello ${this.greeting}`;
  }
}
let greeter = new Creeter("world!");
// console.log(greeter.greet());

// // 继承
class Animal {
  name: string;
  //  构造函数
  constructor(name: string) {
    this.name = name;
  }
  move(distanceInMerters: number = 0) {
    console.log(`${this.name}有了${distanceInMerters}天/`);
  }
}
// Snake继承Animal
class Snake extends Animal {
  constructor(name: string) {
    super(name)
  }
  move(distanceInMerters: number = 5) {
    super.move(distanceInMerters);
  }
}

class Horse extends Animal {
  constructor(name: string) {
    super(name)
  };
  move(distanceInMerters: number = 5) {
    console.log(`再稍等一下~~`);
    super.move(distanceInMerters);
  }
}


// let sam = new Snake(`学习Ts-->`);
// let  tom: Horse = new Horse(`深度学习-->`);
// sam.move();
// tom.move(36);

// 修饰符
// 公有的修饰符:public:public 是ts默认的,不加默认public
class PublicAnimal {
  public name: string;
  public constructor(theName: string) {
    this.name = theName;
  }
  public move(distanceInMerters: number = 5) {
    console.log(`${this.name}move${distanceInMerters}`);
  }
}

// 理解private：当成员被标记成 private时，它就不能在声明它的类的外部访问

class PrivateAnimal {
  private name: string;
  constructor(theName: string) {
    this.name = theName;
  }
}
class Rhino extends PrivateAnimal {
  constructor() {
    super("Rhino");
  }
}
class Employee {
  private name: string;
  constructor(theName: string) {
    this.name = theName;
  }
}
// let animal = new PrivateAnimal('Animal');
// console.log(animal);//Animal { name: 'Animal' }
// let rhino = new Rhino();
// console.log(rhino);//Rhino { name: 'Rhino' }
// let employee = new Employee('Employee');
// console.log(employee);//Employee { name: 'Employee' }
// console.log(animal = rhino);//Rhino { name: 'Rhino' }
// animal = employee;// 错误: Animal 与 Employee 不兼容.不是共用同一个name

// 理解 protected
// protected修饰符与 private修饰符的行为很相似，但有一点不同， protected成员在派生类中仍然可以访问
class Person {
  protected name: string;
  constructor(theName: string) {
    this.name = theName;
  }
}

class Employees extends Person {
  private department: string;

  constructor(name: string, department: string) {
    super(name)
    this.department = department;
  }

  public getElevatorPitch() {
    return `Hello, my name is ${this.name} and I work in ${this.department}.`;
  }
}

// let howard = new Employee('Howard', 'Sales');
// console.log(howard.getElevatorPich());//你好,这是继承Person()的Employee(),名字 Howard 并且工作是 Sales
// 与private能在派生类使用但是不能直接使用
// console.log(howard.name);//编译错误

// 储存器
let passcode = "secret passcode";
class Employeeac {
  private _fullName: string;

  get fullName(): string {
    return this._fullName;
  }

  set fullName(newName: string) {
    if (passcode && passcode == "secret passcode") {
      this._fullName = newName;
    }
    else {
      console.log("Error: Unauthorized update of employee!");
    }
  }
}

let employee = new Employeeac();
employee.fullName = "Bob Smith";
if (employee.fullName) {
  console.log(employee.fullName);
}